package br.poli.mesaterapeutica.XMLSocket;

import java.awt.GraphicsDevice;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import org.uweschmidt.wiimote.whiteboard.WiimoteDataHandler;
import org.uweschmidt.wiimote.whiteboard.WiimoteWhiteboard;
import org.uweschmidt.wiimote.whiteboard.WiimoteDataHandler.WiimoteDataListener;
import org.uweschmidt.wiimote.whiteboard.calibration.WiimoteCalibration;
import org.uweschmidt.wiimote.whiteboard.calibration.WiimoteCalibration.CalibrationEvent;
import org.uweschmidt.wiimote.whiteboard.calibration.WiimoteCalibration.CalibrationEventListener;
import org.uweschmidt.wiimote.whiteboard.ds.IRDot;
import org.uweschmidt.wiimote.whiteboard.ds.Wiimote;
import org.uweschmidt.wiimote.whiteboard.mouse.smoothing.AdaptiveExponentialSmoothing;
import org.uweschmidt.wiimote.whiteboard.preferences.WWPreferences;
import org.uweschmidt.wiimote.whiteboard.preferences.WWPreferences.PreferencesListener;

import de.sciss.net.OSCBundle;
import de.sciss.net.OSCClient;
import de.sciss.net.OSCMessage;
import de.sciss.net.OSCServer;

public class XMLSocketFlash implements PreferencesListener, WiimoteDataListener, CalibrationEventListener{


	private Point[] last;	
	private int port = -1;
	private String host = null;
	private ServerSocket server = null;
	private Socket socket = null;
	private BufferedReader data_in = null;
	private PrintWriter data_out = null;
	private char EOF = (char)0x00;
	private AdaptiveExponentialSmoothing[] smooth;
	private int nojo;
	private Rectangle bounds;
	private WiimoteDataHandler dh;
	private WiimoteCalibration calibration;
	private static final WWPreferences prefs = WWPreferences.getPreferences();

	public XMLSocketFlash(WiimoteDataHandler dh, WiimoteCalibration calibration) {

		this.dh = dh;
		this.calibration = calibration;
		calibration.addCalibrationEventListener(this);
		prefs.addPreferencesListener(this);
		this.smooth = new AdaptiveExponentialSmoothing[4];
		for(int i=0;i<4;i++){
			this.smooth[i] = new AdaptiveExponentialSmoothing();
		}

		nojo = 0;

		update();
		//System.out.println("criou");
	}

	private void update() {
		try {
			if (prefs.isSocketEnabled()) {
				if (server != null){
					
					server.close();
					}

					last = new Point[4];
					port = prefs.getTuioPort();
					getScreenSize();

					System.out.println("Server created");
					server = new ServerSocket(port);

					if (prefs.isServerEnabled() &&  socket == null){
						System.out.println("Waiting for connections...");
						try {
							server.setSoTimeout(15000);
							socket = server.accept();
							if(socket != null){

								data_in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
								data_out = new PrintWriter(socket.getOutputStream());

								data_out.println("Welcome!" + EOF);
								data_out.flush();
								prefs.setServerEnabled(false);}

						} catch (Exception e) {
							prefs.setServerEnabled(false);
							e.printStackTrace();

						}
					}				

					dh.addWiimoteDataListener(this);
				
			} else {
				dh.removeWiimoteDataListener(this);
				if(socket!=null)socket.close();
				if (server != null)server.close();
				server = null;
				socket = null;
			}


		} catch (IOException e) {
			e.printStackTrace();
			WiimoteWhiteboard.getLogger().log(Level.WARNING, "Socket transmission error.", e);
		}
	}

	public void preferencesChanged() {
		update();
		//System.out.println("Mudou config");
	}

	public void calibrationEvent(CalibrationEvent e) {
		if (e == CalibrationEvent.SCREEN_CHANGED) {
			getScreenSize();
		}
	}

	private void getScreenSize() {
		GraphicsDevice screen = calibration.getScreen();
		if (screen != null)
			bounds = screen.getDefaultConfiguration().getBounds();
	}

	public void irWarped(Map<Wiimote, IRDot[]> data, Point[] points) {

		//System.out.println("evento!!");
		if (server == null) return;
		// return if all lights are off now and were previously
		if ((points[0] == null && points[1] == null && points[2] == null && points[3] == null) &&
				(last[0] == null && last[1] == null && last[2] == null && last[3] == null))
			return;

		String message = new String();
		// cursor data
		if(nojo == 0){
			nojo = nojo + 1;
			for (int i = 0; i < 4; i++) {
				Point p = points[i];
				if(socket!=null){

					if (p != null) {
						p = smooth[i].translate(p);
						p.translate(-bounds.x, -bounds.y);
						if (i != 3)message = message.concat(" P" + String.valueOf(i) +"; "+ String.valueOf((float)Math.max(0, Math.min(p.x, bounds.width)) / bounds.width) +"; "+ String.valueOf((float)Math.max(0, Math.min(p.y, bounds.height)) / bounds.height)+"; " );
						else{message = message.concat(" P" + String.valueOf(i) +"; "+ String.valueOf((float)Math.max(0, Math.min(p.x, bounds.width)) / bounds.width) +"; "+ String.valueOf((float)Math.max(0, Math.min(p.y, bounds.height)) / bounds.height) );}
						//System.out.println( i + "; " + (float)Math.max(0, Math.min(p.x, bounds.width)) / bounds.width +"; "+ (float)Math.max(0, Math.min(p.y, bounds.height)) / bounds.height);
					}
					else if (p==null){
						if ( i != 3)message = message.concat(" P" + String.valueOf(i) +"; "+ String.valueOf((float)-1) +"; "+ String.valueOf((float)-1) +"; ");
						else {message = message.concat(" P" + String.valueOf(i) +"; "+ String.valueOf((float)-1) +"; "+ String.valueOf((float)-1));}
					//System.out.println( String.valueOf(i) +"; "+ String.valueOf((float)-1) +"; "+ String.valueOf((float)-1));
					}}}}
		else{
			nojo = 0;}
		//else if (nojo ==2)
		//{ nojo = 0;}



		if(socket!=null){
			if(message!=null){
				System.out.println(message);
				message = message.concat(String.valueOf(EOF));

				data_out.println(message);
				data_out.flush();
			}
		}

	}

	public void batteryLevel(Wiimote wiimote, double level) {
	}

	public void irLights(Wiimote wiimote, IRDot[] lights) {
	}

	public void wiimoteConnected(Wiimote wiimote) {
	}

	public void wiimoteDisconnected(Wiimote wiimote) {
	}



}


